fix(cli): detect WinGet Claude Code on Windows - #6647
diegosouzapw merged 7 commits into
Conversation
… (ABI 148) (diegosouzapw#6605) fix(electron): bump electron 42→43 + rebuild better-sqlite3 from source against the Electron ABI (148). Electron 43 raises NODE_MODULE_VERSION to 148; better-sqlite3@12.11.1 has no electron-v148 prebuild, so the packaged app died with 'Nenhum driver SQLite disponível'. prepare-electron-standalone now compiles better-sqlite3 from source against the electron headers into build/Release (where 'bindings' resolves it). Validated by Electron Package Smoke (green) + local (node_register_module_v148). Supersedes diegosouzapw#6378. (--admin: the only reds are SonarQube/SonarCloud failing on a coverage-report artifact digest-mismatch — a GitHub Actions infra flake, not this diff; Sonar is green on main and the diff touches only the electron build.)
…iegosouzapw#6588) deps: bump the development group (6 updates). Rebased onto current main; all checks green after the electron-smoke fix (diegosouzapw#6605).
…7) + production deps bump (diegosouzapw#6620) fix(proxy): force CONNECT tunnel for HTTP proxied requests (undici 8.7) + production deps bump. undici 8.6+ changed ProxyAgent to forward plain-HTTP via request-proxy instead of CONNECT, breaking OAuth refresh through a connection proxy (501). proxyDispatcher now passes proxyTunnel:true. Validated: Unit Tests 3/8 (the OAuth-proxy test) green, new regression test green (fails without the fix on undici 8.7), SonarQube green. Supersedes diegosouzapw#6380. (--admin: the only red is Electron Package Smoke failing on a next-build artifact 'digest-mismatch' — a GitHub Actions infra flake corrupting the asar ('file data stream has unexpected number of bytes'); the better-sqlite3 rebuild itself succeeded (gyp ok) and the electron path is unchanged from diegosouzapw#6605 which passed the smoke. Not this diff.)
left a comment
There was a problem hiding this comment.
Code Review
This pull request adds support for detecting the WinGet installation path of Claude Code on Windows and includes a corresponding unit test. The reviewer suggested mocking the process.env.LOCALAPPDATA environment variable in the test to ensure it is robust and independent of the host environment.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| it("should include the WinGet Anthropic.ClaudeCode install path", () => { | ||
| const localAppData = process.env.LOCALAPPDATA; | ||
| const expected = localAppData | ||
| ? path.join( | ||
| localAppData, | ||
| "Microsoft", | ||
| "WinGet", | ||
| "Packages", | ||
| "Anthropic.ClaudeCode_Microsoft.Winget.Source_8wekyb3d8bbwe", | ||
| "claude.exe" | ||
| ) | ||
| : null; | ||
|
|
||
| if (process.platform !== "win32" || !expected) return; | ||
|
|
||
| assert.ok( | ||
| getKnownToolPaths("claude").includes(expected), | ||
| "Claude Code installed by WinGet should be discoverable without CLI_CLAUDE_BIN" | ||
| ); | ||
| }); |
There was a problem hiding this comment.
The test currently relies on the host's actual process.env.LOCALAPPDATA environment variable. If LOCALAPPDATA is missing or is set to a custom path outside the allowed parent directories (which are validated against the user's home directory in validateEnvPath), the test will fail or silently skip. Mocking process.env.LOCALAPPDATA to a deterministic, valid path (such as path.join(os.homedir(), 'AppData', 'Local')) ensures the test is robust and independent of the host environment.
it("should include the WinGet Anthropic.ClaudeCode install path", () => {
if (process.platform !== "win32") return;
const originalLocalAppData = process.env.LOCALAPPDATA;
const home = os.homedir();
const testLocalAppData = path.join(home, "AppData", "Local");
process.env.LOCALAPPDATA = testLocalAppData;
try {
const expected = path.join(
testLocalAppData,
"Microsoft",
"WinGet",
"Packages",
"Anthropic.ClaudeCode_Microsoft.Winget.Source_8wekyb3d8bbwe",
"claude.exe"
);
assert.ok(
getKnownToolPaths("claude").includes(expected),
"Claude Code installed by WinGet should be discoverable without CLI_CLAUDE_BIN"
);
} finally {
if (originalLocalAppData !== undefined) {
process.env.LOCALAPPDATA = originalLocalAppData;
} else {
delete process.env.LOCALAPPDATA;
}
}
});
commented
Jul 8, 2026
|
Thanks for this — clean, small, well-scoped fix. The new WinGet path sits correctly inside the existing |
…s-claude-winget-detection
…roxy files belong to diegosouzapw#6620, not this PR) Restores electron/package-lock.json, electron/package.json, package-lock.json, package.json, open-sse/utils/proxyDispatcher.ts, scripts/build/prepare-electron-standalone.mjs and tests/unit/proxy-dispatcher-family.test.ts to origin/release/v3.8.47's content. The PR fork branched from a state of main that already includes diegosouzapw#6620 (proxy CONNECT tunnel fix + deps bump), which is not yet synced into release/v3.8.47 — the 3-way merge would otherwise silently carry that unrelated content into this doc-only PR. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
…uzapw#6647 (1100->1110) The file was already exactly at the frozen 1100-line cap on release/v3.8.47. PR diegosouzapw#6647's WinGet Claude Code detection path adds 10 lines (irreducible — the 62-char package folder name forces Prettier's 100-char width to break the path.join call across the same multi-line form used by every other long path in this function), tripping the Fast Quality Gates check:file-size job. Bumping the frozen cap to the file's real new size per the documented allowlist-with-justification policy (this is a pass/fail policy gate, not the ratchet metrics system). Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Summary
Why
WinGet installs Claude Code at
%LOCALAPPDATA%\Microsoft\WinGet\Packages\Anthropic.ClaudeCode_Microsoft.Winget.Source_8wekyb3d8bbwe\claude.exe, which was not in OmniRoute's fallback lookup list. Users could work around it withCLI_CLAUDE_BIN, but OmniRoute should detect the WinGet install automatically.Test
node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit tests/unit/cli-runtime-detection.test.ts